package com.pengliu.common.mybatis.model;

import com.pengliu.common.mybatis.model.ModelExample.Criterion;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
/**
 * user: pengliu
 * date: 2017年10月17日
 * desc:
 * @author pengliu
 */
public class SearchFilter {
	
	private static final int INT90 = 90;
	
	private static final int INT65 = 65;

	public enum Operator {

		//运算符(=)
		EQ(" = "),

		NEQ(" <> "),

		GT(" > "),

		GTE(" >= "),

		LT(" < "),

		LTE(" <= "),

		LIKE(" like "),

		NLIKE(" not like "),

		IN(" in "),

		NIN(" not in "),

		NULL(" is null "),

		NNULL(" is not null "),
		
		OR(" or "),

		GROUPBY(""),

		ORDERBY(""),

		;

		private final String operator;

		private Operator(String operator) {
			this.operator = operator;
		}

		public String getOperator() {
			return operator;
		}

		public static Operator getByOperator(String operator) {
			for (Operator o : values()) {
				if (o.toString().equals(operator)) {
					return o;
				}
			}
			return null;
		}

	}

	public static void filter(ModelExample example, HttpServletRequest request) {

		List<Criterion> criteria = new ArrayList<Criterion>();

		String groupByClause = null;

		String orderByClause = null;
		
		/** 扩展查询 title like @ or editor_name like @ or auditor_name like @ or publisher_name like @*/
		String queryExpand = null;

		Entry<String, String[]> entry = null;
		String[] value = null;
		String key = null;
		String[] names = null;
		Operator operator = null;
		String fieldName = null;
		String condition = null;
		Criterion criterion = null;
		for (Object obj : request.getParameterMap().entrySet()) {
			entry = (Entry<String, String[]>)obj;
			value = entry.getValue();

			if (ArrayUtils.isEmpty(value) || StringUtils.isBlank(value[0])) {
				continue;
			}

			key = entry.getKey();

			names = StringUtils.split(key, "_");

			if (names.length != 2) {
				continue;
			}

			operator = Operator.getByOperator(names[0].toUpperCase());

			if (operator == null) {
				continue;
			}

			fieldName = names[1];

			if (!StringUtils.isAlphanumeric(fieldName.replace(".", ""))) {
				continue;
			}

			condition = toLowercaseWithUnderscore(fieldName)
					+ operator.getOperator();

			switch (operator) {

			case EQ:
			case NEQ:
			case GT:
			case GTE:
			case LT:
			case LTE:
				criterion = new Criterion(condition, value[0]);
				break;

			case LIKE:
			case NLIKE:
				criterion = new Criterion(condition, "%" + value[0] + "%");
				break;

			case IN:
			case NIN:
				criterion = new Criterion(condition, Arrays.asList(ArrayUtils
						.addAll(value[0].split(","),
								ArrayUtils.remove(value, 0))));
				break;

			case NULL:
			case NNULL:
				criterion = new Criterion(condition);
				break;
				
			case OR:
				if("titleEditor".equalsIgnoreCase(names[1])) {
					queryExpand = "(title like '%" + value[0] + "%' or editor_name like '%" + value[0] + "%')";
				} else if("titleAuditor".equalsIgnoreCase(names[1])) {
					queryExpand = "(title like '%" + value[0] + "%' or auditor_name like '%" + value[0] + "%')";
				} else if("titlePublisher".equalsIgnoreCase(names[1])) {
					queryExpand = "(title like '%" + value[0] + "%' or publisher_name like '%" + value[0] + "%')";
				}
				break;

			case GROUPBY:
				groupByClause = condition;
				break;

			case ORDERBY:
				if ("DESC".equalsIgnoreCase(value[0])) {
					orderByClause = condition + " DESC ";
				} else {
					orderByClause = condition + " ASC ";
				}
				break;

			default:
				break;
			}

			if (criterion != null) {
				criteria.add(criterion);
			}
		}
		if(queryExpand != null) {
			if(criteria.size() == 0) {
				queryExpand = " where " + queryExpand;
			} else {
				queryExpand = " and " + queryExpand;
			}
		}
		
		example.addCriteria(criteria);
		example.setQueryExpand(queryExpand);
		example.setGroupByClause(groupByClause);
		example.setOrderByClause(orderByClause);

	}

	/**
	 * 将字符串由驼峰转换为下划线形式的
	 */
	public static String toLowercaseWithUnderscore(String str) {

		if (StringUtils.isBlank(str)) {
			return null;
		}

		StringBuffer hs = new StringBuffer();
		char[] chars = str.toCharArray();
		char char0 = chars[0];

		if (char0 >= INT65 && char0 <= INT90) {
			hs.append((char) (char0 + 32));
		}else {
			hs.append(char0);
		}

		for (int i = 1; i < chars.length; i++) {
			char c = chars[i];
			if (c >= INT65 && c <= INT90) {
				hs.append('_').append((char) (c + 32));
			}else {
				hs.append(c);
			}
		}

		return hs.toString();
	}

}
